home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Special 26
/
AMIGAplus Sonderheft 26 (2000)(Falke)(DE)(Track 1 of 2)[!].iso
/
Updates
/
Librarys
/
asyncioppc
/
source
/
async_ppc.c
next >
Wrap
C/C++ Source or Header
|
2000-07-04
|
13KB
|
522 lines
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/powerpc_protos.h>
#include <libraries/asyncio.h>
#include <exec/memory.h>
#include <string.h>
#define D_S(type,name) char a_##name[ sizeof( type )+3]; type *name=(type *)((LONG)(a_##name+3)&~3);
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
static void copymem(UBYTE *s,UBYTE *d,ULONG len)
{
ULONG l=len&7;
len-=l;
while(l--) *(d++)=*(s++);
while(len)
{
*(((double *)d)++)=*(((double *)s)++);
len-=8;
}
}
static VOID AS_SendPacket(struct AsyncFile *file,APTR arg2)
{
file->af_Packet.sp_Pkt.dp_Port=&file->af_PacketPort;
file->af_Packet.sp_Pkt.dp_Arg2=(LONG)arg2;
PutXMsgPPC(file->af_Handler,&file->af_Packet.sp_Msg);
file->af_PacketPending=TRUE;
}
static LONG AS_WaitPacket(AsyncFile *file)
{
LONG bytes;
if(file->af_PacketPending)
{
while(1)
{
file->af_PacketPort.mp_Flags=PA_SIGNAL;
RemovePPC((struct Node *)WaitPort(&file->af_PacketPort));
/*
This dummy call is absolutely necessary to avoid lock-up
in some strange cases, e.g. accessing very long files !!, Dont remove it !!
*/
// SPrintF(0,0);
file->af_PacketPort.mp_Flags=PA_IGNORE;
file->af_PacketPending=FALSE;
bytes=file->af_Packet.sp_Pkt.dp_Res1;
if(bytes>=0) return bytes;
if(ErrorReport(file->af_Packet.sp_Pkt.dp_Res2,REPORT_STREAM,file->af_File,NULL)) return -1;
AS_SendPacket(file,file->af_Buffers[file->af_ReadMode?file->af_CurrentBuf:1-file->af_CurrentBuf]);
}
}
SetIoErr(file->af_Packet.sp_Pkt.dp_Res2);
return file->af_Packet.sp_Pkt.dp_Res1;
}
static VOID AS_RecordSyncFailure(struct AsyncFile *file)
{
file->af_LastRes1=file->af_Packet.sp_Pkt.dp_Res1;
file->af_LastBytesLeft=file->af_BytesLeft;
file->af_Packet.sp_Pkt.dp_Res1=-1;
file->af_Packet.sp_Pkt.dp_Res2=IoErr();
file->af_BytesLeft=0;
}
static VOID AS_RequeuePacket(AsyncFile *file)
{
AddHeadPPC(&file->af_PacketPort.mp_MsgList,&file->af_Packet.sp_Msg.mn_Node);
file->af_PacketPending=TRUE;
}
struct AsyncFile *AS_OpenAsyncFH(BPTR handle,LONG mode,LONG bufferSize,BOOL closeIt)
{
FileHandle *fh;
AsyncFile *file=NULL;
BPTR lock=NULL;
LONG blockSize,blockSize2;
D_S(struct InfoData,infoData);
if(mode==MODE_READ)
{
if(handle) lock=DupLockFromFH(handle);
}
else
{
if(mode==MODE_APPEND)
{
if(handle)
{
if(Seek(handle,0,OFFSET_END)<0)
{
if(closeIt) Close(handle);
handle=NULL;
}
}
}
if(handle) lock=ParentOfFH(handle);
}
if(handle)
{
blockSize=512;
blockSize2=1024;
if(lock)
{
if(Info(lock,infoData))
{
blockSize=infoData->id_BytesPerBlock;
blockSize2=blockSize*2;
bufferSize=((bufferSize+blockSize2-1)/blockSize2)*blockSize2;
}
UnLock(lock);
}
for(;;)
{
if(file=AllocVecPPC(sizeof(AsyncFile)+bufferSize+15,MEMF_PUBLIC|MEMF_ANY,0)) break;
else
{
if(bufferSize>blockSize2) bufferSize-=blockSize2;
else break;
}
}
if(file)
{
file->af_File=handle;
file->af_ReadMode=(mode==MODE_READ);
file->af_BlockSize=blockSize;
file->af_CloseFH=closeIt;
fh=(FileHandle *)BADDR(file->af_File);
file->af_Handler=fh->fh_Type;
file->af_BufferSize=(ULONG)bufferSize/2;
file->af_Buffers[0]=(UBYTE *)(((ULONG)file+sizeof(AsyncFile)+15)&0xfffffff0);
file->af_Buffers[1]=file->af_Buffers[0]+file->af_BufferSize;
file->af_CurrentBuf=0;
file->af_SeekOffset=0;
file->af_PacketPending=FALSE;
file->af_SeekPastEOF=FALSE;
file->af_PacketPort.mp_MsgList.lh_Head=(struct Node *)&file->af_PacketPort.mp_MsgList.lh_Tail;
file->af_PacketPort.mp_MsgList.lh_Tail=NULL;
file->af_PacketPort.mp_MsgList.lh_TailPred=(struct Node *)&file->af_PacketPort.mp_MsgList.lh_Head;
file->af_PacketPort.mp_Node.ln_Type=NT_MSGPORT;
file->af_PacketPort.mp_Node.ln_Name=NULL;
file->af_PacketPort.mp_Flags=PA_IGNORE;
file->af_PacketPort.mp_SigBit=SIGB_SINGLE;
file->af_PacketPort.mp_SigTask=FindTask(NULL);
file->af_Packet.sp_Pkt.dp_Link=&file->af_Packet.sp_Msg;
file->af_Packet.sp_Pkt.dp_Arg1=fh->fh_Arg1;
file->af_Packet.sp_Pkt.dp_Arg3=file->af_BufferSize;
file->af_Packet.sp_Pkt.dp_Res1=0;
file->af_Packet.sp_Pkt.dp_Res2=0;
file->af_Packet.sp_Msg.mn_Node.ln_Name=(STRPTR)&file->af_Packet.sp_Pkt;
file->af_Packet.sp_Msg.mn_Node.ln_Type=NT_MESSAGE;
file->af_Packet.sp_Msg.mn_Length=sizeof(struct StandardPacket);
if(mode==MODE_READ)
{
file->af_Packet.sp_Pkt.dp_Type=ACTION_READ;
file->af_BytesLeft=0;
file->af_Offset=file->af_Buffers[1];
if(file->af_Handler) AS_SendPacket(file,file->af_Buffers[0]);
}
else
{
file->af_Packet.sp_Pkt.dp_Type=ACTION_WRITE;
file->af_BytesLeft=file->af_BufferSize;
file->af_Offset=file->af_Buffers[0];
}
}
else
{
if(closeIt) Close(handle);
}
}
return file;
}
struct AsyncFile * __saveds OpenAsyncPPC(struct AsyncIOBase *base,STRPTR fileName,LONG mode,LONG bufferSize)
{
static const WORD PrivateOpenModes[]={MODE_OLDFILE,MODE_NEWFILE,MODE_READWRITE};
BPTR handle;
AsyncFile *file=NULL;
if(handle=Open(fileName,PrivateOpenModes[mode]))
{
if(!(file=AS_OpenAsyncFH(handle,mode,bufferSize,TRUE))) Close(handle);
}
return file;
}
struct AsyncFile * __saveds OpenAsyncFromFHPPC(struct AsyncIOBase *base,BPTR handle,LONG mode,LONG bufferSize)
{
return AS_OpenAsyncFH(handle,mode,bufferSize,FALSE);
}
LONG __saveds CloseAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file)
{
LONG result;
if(file)
{
result=AS_WaitPacket(file);
if(result>=0)
{
if(!file->af_ReadMode)
{
if(file->af_BufferSize>file->af_BytesLeft)
{
result=Write(file->af_File,file->af_Buffers[file->af_CurrentBuf],file->af_BufferSize-file->af_BytesLeft);
}
}
}
if(file->af_CloseFH) Close(file->af_File);
FreeVecPPC(file);
}
else result=-1;
return result;
}
LONG __saveds ReadAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
{
LONG totalBytes=0;
LONG bytesArrived;
while(numBytes>file->af_BytesLeft)
{
copymem(file->af_Offset,buffer,file->af_BytesLeft);
numBytes-=file->af_BytesLeft;
buffer=(APTR)((ULONG)buffer+file->af_BytesLeft);
totalBytes+=file->af_BytesLeft;
file->af_BytesLeft=0;
bytesArrived=AS_WaitPacket(file);
if(bytesArrived<=0)
{
if(bytesArrived==0) return(totalBytes);
return -1;
}
AS_SendPacket(file,file->af_Buffers[1-file->af_CurrentBuf]);
if(file->af_SeekOffset>bytesArrived) file->af_SeekOffset=bytesArrived;
file->af_Offset=file->af_Buffers[file->af_CurrentBuf]+file->af_SeekOffset;
file->af_CurrentBuf=1-file->af_CurrentBuf;
file->af_BytesLeft=bytesArrived-file->af_SeekOffset;
file->af_SeekOffset=0;
}
copymem(file->af_Offset,buffer,numBytes);
file->af_BytesLeft-=numBytes;
file->af_Offset+=numBytes;
return totalBytes+numBytes;
}
LONG __saveds PeekAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
{
if(!file->af_BytesLeft)
{
LONG bytes;
if((bytes=ReadAsyncPPC(base,file,&bytes,1))<=0) return bytes;
--file->af_Offset;
++file->af_BytesLeft;
}
numBytes=MIN(numBytes,file->af_BytesLeft);
copymem(file->af_Offset,buffer,numBytes);
return numBytes;
}
LONG __saveds ReadCharAsyncPPC(struct AsyncIOBase *base,AsyncFile *file)
{
UBYTE ch;
if(file->af_BytesLeft)
{
ch=*file->af_Offset;
--file->af_BytesLeft;
++file->af_Offset;
return ch;
}
if(ReadAsyncPPC(base,file,&ch,1)>0) return ch;
return -1;
}
STRPTR __saveds FGetsLenAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR buf,LONG numBytes,LONG *len)
{
UBYTE *p;
LONG length=0;
p=(UBYTE *)buf;
if(--numBytes<=0) return 0;
while(TRUE)
{
UBYTE *ptr;
LONG i,count;
ptr=(UBYTE *)file->af_Offset;
if(count=file->af_BytesLeft)
{
count=MIN(count,numBytes);
for(i=0;(i<count)&&(*ptr!='\n');++i) *p++=*ptr++;
length+=i;
if(i<count)
{
*p++='\n';
++i;
length+=1;
}
file->af_BytesLeft-=i;
file->af_Offset+=i;
if((i>=numBytes)||(*(p-1)=='\n')) break;
numBytes-=i;
}
if(ReadAsyncPPC(base,file,p,1)<1) break;
--numBytes;
++length;
if(*p++=='\n') break;
}
*p='\0';
*len=length;
if(p==(UBYTE *)buf) return 0;
return buf;
}
STRPTR __saveds FGetsAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR buf,LONG numBytes)
{
LONG len;
return FGetsLenAsyncPPC(base,file,buf,numBytes,&len);
}
LONG __saveds ReadLineAsyncPPC(struct AsyncIOBase *base,AsyncFile *file,APTR buffer,LONG bufSize)
{
LONG len;
if(FGetsLenAsyncPPC(base,file,buffer,bufSize,&len))
{
UBYTE *end;
end=((UBYTE *)buffer)+len-1;
if(*end!='\n')
{
UBYTE ch=0;
while(TRUE)
{
UBYTE *ptr;
LONG i,count;
ptr=(UBYTE *)file->af_Offset;
if(count=file->af_BytesLeft)
{
for(i=0;(i<count)&& (*ptr!='\n');++i,++ptr)
{
}
if(i<count)
{
ch='\n';
++i;
}
file->af_BytesLeft-=i;
file->af_Offset+=i;
if(i<count) break;
}
if(ReadAsyncPPC(base,file,&ch,1)<1) break;
if(ch=='\n') break;
}
if(ch=='\n')
{
*end++='\n';
*end='\0';
}
}
}
return len;
}
static __saveds ULONG GetFileSize(AsyncFile *file,LONG *size)
{
D_S(struct FileInfoBlock,fib);
if(!ExamineFH(file->af_File,fib))
{
AS_RecordSyncFailure(file);
return FALSE;
}
*size=fib->fib_Size;
return TRUE;
}
LONG __saveds SeekAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,LONG position,LONG mode)
{
LONG current,target,roundTarget,filePos;
LONG minBuf,maxBuf,bytesArrived,diff;
LONG fileSize;
bytesArrived=AS_WaitPacket(file);
if(bytesArrived<0)
{
if(file->af_SeekPastEOF)
{
bytesArrived=file->af_LastRes1;
file->af_BytesLeft=file->af_LastBytesLeft;
}
else return -1;
}
if(file->af_ReadMode)
{
filePos=Seek(file->af_File,0,OFFSET_CURRENT);
if(filePos<0)
{
AS_RecordSyncFailure(file);
return -1;
}
current=filePos-(file->af_BytesLeft+bytesArrived)+file->af_SeekOffset;
if(mode==MODE_CURRENT) target=current+position;
else if(mode==MODE_START) target=position;
else
{
if(!GetFileSize(file,&fileSize)) return -1;
target=fileSize+position;
}
minBuf=current-(LONG)(file->af_Offset-file->af_Buffers[1-file->af_CurrentBuf]);
maxBuf=current+file->af_BytesLeft+bytesArrived;
diff=target-current;
if((target<minBuf)||(target>=maxBuf))
{
if(target>=maxBuf)
{
if(!GetFileSize(file,&fileSize)) return -1;
if(target>fileSize)
{
file->af_SeekPastEOF=TRUE;
SetIoErr(ERROR_SEEK_ERROR);
AS_RecordSyncFailure(file);
return -1;
}
}
roundTarget=(target/file->af_BlockSize)*file->af_BlockSize;
if(Seek(file->af_File,roundTarget-filePos,OFFSET_CURRENT)<0)
{
AS_RecordSyncFailure(file);
return -1;
}
AS_SendPacket(file,file->af_Buffers[0]);
file->af_SeekOffset=target-roundTarget;
file->af_BytesLeft=0;
file->af_CurrentBuf=0;
file->af_Offset=file->af_Buffers[1];
}
else if((target<current)||(diff<=file->af_BytesLeft))
{
AS_RequeuePacket(file);
file->af_BytesLeft-=diff;
file->af_Offset+=diff;
if(file->af_SeekPastEOF) file->af_Packet.sp_Pkt.dp_Res1=file->af_LastRes1;
}
else
{
AS_SendPacket(file,file->af_Buffers[1-file->af_CurrentBuf]);
diff-=file->af_BytesLeft-file->af_SeekOffset;
file->af_Offset=file->af_Buffers[file->af_CurrentBuf]+diff;
file->af_BytesLeft=bytesArrived-diff;
file->af_SeekOffset=0;
file->af_CurrentBuf=1-file->af_CurrentBuf;
}
}
else
{
if(file->af_BufferSize>file->af_BytesLeft)
{
if(Write(file->af_File,file->af_Buffers[file->af_CurrentBuf],file->af_BufferSize-file->af_BytesLeft)<0)
{
AS_RecordSyncFailure(file);
return -1;
}
}
current=Seek(file->af_File,position,mode);
if(current<0)
{
AS_RecordSyncFailure(file);
return -1;
}
file->af_BytesLeft=file->af_BufferSize;
file->af_CurrentBuf=0;
file->af_Offset=file->af_Buffers[0];
}
if(file->af_SeekPastEOF) file->af_SeekPastEOF=FALSE;
SetIoErr(0);
return current;
}
LONG __saveds WriteAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
{
LONG totalBytes=0;
if(!file->af_Handler)
{
file->af_Offset=file->af_Buffers[0];
file->af_BytesLeft=file->af_BufferSize;
return numBytes;
}
while(numBytes>file->af_BytesLeft)
{
if(file->af_BytesLeft)
{
copymem(buffer,file->af_Offset,file->af_BytesLeft);
numBytes-=file->af_BytesLeft;
buffer=(APTR)((ULONG)buffer+file->af_BytesLeft);
totalBytes+=file->af_BytesLeft;
}
if(AS_WaitPacket(file)<0) return -1;
AS_SendPacket(file,file->af_Buffers[file->af_CurrentBuf]);
file->af_CurrentBuf=1-file->af_CurrentBuf;
file->af_Offset=file->af_Buffers[file->af_CurrentBuf];
file->af_BytesLeft=file->af_BufferSize;
}
copymem(buffer,file->af_Offset,numBytes);
file->af_BytesLeft-=numBytes;
file->af_Offset+=numBytes;
return totalBytes+numBytes;
}
LONG __saveds WriteCharAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,ULONG ch)
{
UBYTE c;
if(file->af_BytesLeft)
{
*file->af_Offset=ch;
--file->af_BytesLeft;
++file->af_Offset;
return 1;
}
c=ch;
return WriteAsyncPPC(base,file,&c,1);
}
LONG __saveds WriteLineAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR line)
{
return WriteAsyncPPC(base,file,line,strlen(line));
}